<!--
  Camera Controls Demo Component

  This demo shows how to work with camera controls in CesiumJS.
  It demonstrates different camera operations and controls.

  Features:
    - Camera flight paths
    - Different camera controls
    - View management
-->

<template>
  <BaseCesiumViewer 
    ref="cesiumViewer" 
    
    @viewer-ready="onViewerReady"
  />
</template>

<script>
import { onUnmounted } from 'vue';
import BaseCesiumViewer from '../core/BaseCesiumViewer.vue';

export default {
  name: 'CameraControlsDemo',
  components: {
    BaseCesiumViewer
  },
  setup() {
    // Store timeout IDs for cleanup
    let timeoutIds = [];

    // This function is called when the Cesium viewer is ready
    const onViewerReady = (payload) => {
      // Check if payload and viewer are valid
      if (!payload || !payload.viewer) {
        console.error('Viewer is not ready or payload is invalid');
        return;
      }
      
      const { viewer, Cesium } = payload;
      
      // Add some sample entities to demonstrate camera controls on
      const entities = [
        {
          name: 'Tokyo',
          position: Cesium.Cartesian3.fromDegrees(139.6917, 35.6895),
          color: Cesium.Color.RED
        },
        {
          name: 'London',
          position: Cesium.Cartesian3.fromDegrees(-0.1278, 51.5074),
          color: Cesium.Color.BLUE
        },
        {
          name: 'New York',
          position: Cesium.Cartesian3.fromDegrees(-74.0059, 40.7128),
          color: Cesium.Color.GREEN
        },
        {
          name: 'Sydney',
          position: Cesium.Cartesian3.fromDegrees(151.2093, -33.8688),
          color: Cesium.Color.YELLOW
        }
      ];

      // Add entities to the viewer
      entities.forEach(entity => {
        viewer.entities.add({
          name: entity.name,
          position: entity.position,
          point: {
            pixelSize: 10,
            color: entity.color,
            outlineColor: Cesium.Color.WHITE,
            outlineWidth: 2
          },
          label: {
            text: entity.name,
            font: '14px sans-serif',
            fillColor: Cesium.Color.WHITE,
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 2,
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            pixelOffset: new Cesium.Cartesian2(0, -15)
          }
        });
      });

      // Set initial view
      viewer.camera.setView({
        destination: Cesium.Cartesian3.fromDegrees(0, 0, 40000000)
      });

      // Demonstrate different camera controls after a delay
      const initialTimeout = setTimeout(() => {
        demonstrateCameraControls(viewer, Cesium);
      }, 2000);
      
      // Store timeout ID for cleanup
      timeoutIds.push(initialTimeout);
    };

    // Function to demonstrate various camera controls
    const demonstrateCameraControls = (viewer, Cesium) => {
      // 1. flyTo - Smooth camera movement to a location
      const timeout1 = setTimeout(() => {
        viewer.camera.flyTo({
          destination: Cesium.Cartesian3.fromDegrees(139.6917, 35.6895, 1000000),
          duration: 3,
          orientation: {
            heading: Cesium.Math.toRadians(0),
            pitch: Cesium.Math.toRadians(-15),
            roll: 0.0
          }
        });
      }, 0);

      // 2. Look at a specific entity
      const timeout2 = setTimeout(() => {
        const tokyoEntity = viewer.entities.values.find(e => e.name === 'Tokyo');
        if (tokyoEntity) {
          viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(140.6917, 36.6895, 500000),
            orientation: {
              direction: Cesium.Cartesian3.subtract(
                tokyoEntity.position.getValue(Cesium.JulianDate.now()),
                viewer.camera.position,
                new Cesium.Cartesian3()
              ),
              up: viewer.camera.up
            },
            duration: 3
          });
        }
      }, 4000);

      // 3. Set view to a rectangle
      const timeout3 = setTimeout(() => {
        viewer.camera.flyTo({
          destination: Cesium.Rectangle.fromDegrees(-15, 35, 25, 60), // Europe
          duration: 3
        });
      }, 8000);

      // 4. Circular rotation around a point
      const timeout4 = setTimeout(() => {
        circularRotationDemo(viewer, Cesium);
      }, 12000);
      
      // Store timeout IDs for cleanup
      timeoutIds.push(timeout1, timeout2, timeout3, timeout4);
    };

    // Function to demonstrate circular rotation
    const circularRotationDemo = (viewer, Cesium) => {
      const center = Cesium.Cartesian3.fromDegrees(-0.1278, 51.5074); // London
      let angle = 0;
      let animationId = null;
      
      const circularRotation = () => {
        angle += 0.02;
        if (angle > Math.PI * 4) { // Rotate twice
          // Reset to top-down view after circular rotation
          viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(0, 0, 40000000),
            duration: 3
          });
          return;
        }

        const radius = 800000;
        const height = 500000;
        const position = new Cesium.Cartesian3(
          center.x + radius * Math.cos(angle),
          center.y + radius * Math.sin(angle),
          center.z + height
        );

        viewer.camera.setView({
          destination: position,
          orientation: {
            direction: Cesium.Cartesian3.subtract(
              center,
              position,
              new Cesium.Cartesian3()
            ),
            up: Cesium.Cartesian3.UNIT_Z
          }
        });

        animationId = requestAnimationFrame(circularRotation);
      };

      animationId = requestAnimationFrame(circularRotation);
      
      // Add a cleanup function for the animation
      const cleanupAnimation = () => {
        if (animationId) {
          cancelAnimationFrame(animationId);
        }
      };
      
      // Store the cleanup function in timeoutIds for later execution
      timeoutIds.push(cleanupAnimation);
    };
    
    // Clean up timeouts and animations when component is unmounted
    onUnmounted(() => {
      timeoutIds.forEach(timeout => {
        if (typeof timeout === 'number') {
          clearTimeout(timeout);
        } else if (typeof timeout === 'function') {
          // Execute cleanup functions for animations
          timeout();
        }
      });
      timeoutIds = [];
    });

    return {
      onViewerReady
    };
  }
};
</script>

<style scoped>
/* 
  Component Styles
  Add any custom styles for your demo here
*/
</style>